package com.hefan.pay.service;

import com.alibaba.fastjson.JSON;
import com.cat.common.entity.ResultBean;
import com.cat.common.meta.PaymentTypeEnum;
import com.cat.common.meta.ResultCode;
import com.cat.common.util.BigDecimalCalUtil;
import com.cat.tiger.util.CollectionUtils;
import com.cat.tiger.util.GlobalConstants;
import com.hefan.common.pay.wechat.*;
import com.hefan.common.util.PayPropertiesUtils;
import com.hefan.pay.bean.*;
import com.hefan.pay.dao.PayReqLogDao;
import com.hefan.pay.itf.ThridPartyPayCallService;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by lxw on 2016/10/12.
 */
@Component("wechatPayService")
public class WechatPayServiceImp implements ThridPartyPayCallService {

    private Logger logger = LoggerFactory.getLogger(WechatPayServiceImp.class);

    @Resource
    private PayReqLogDao payReqLogDao;


    @Override
    public ResultBean thridPartyPayCall(PaymentTypeEnum paymentTypeEnum, TradeLog tradeLog, PayExtendVo payExtendVo) {
        ResultBean resultBean = new ResultBean(ResultCode.SUCCESS,null);
        try {
            int payAmount = Integer.valueOf(BigDecimalCalUtil.mul(payExtendVo.getPayAmount(),"100",0));
            //组装请求下单参数对象
            WechatPrePayReqVo wechatPrePayReqVo = new WechatPrePayReqVo(GlobalConstants.PAY_PRODUCT_NAME,
                    GlobalConstants.PAY_PRODUCT_NAME, payExtendVo.getOrderId(),
                    payAmount, payExtendVo.getClientIp(),PayPropertiesUtils.getString("wechat.payNotifyUrl"),
                    paymentTypeEnum.getWechatTradeType(),
                    new Date(), payExtendVo.getOrderId(), GlobalConstants.PAY_PRODUCT_ID);
            WechatPayHttpsRequest wechatPayHttpsRequest = new WechatPayHttpsRequest();
            //解决XStream对出现双下划线的bug
            XStream xStreamForRequestPostData = new XStream(new DomDriver("UTF-8", new XmlFriendlyNameCoder("-_", "_")));
            //将要提交给API的数据对象转换成XML格式数据Post给API
            String postDataXML = xStreamForRequestPostData.toXML(wechatPrePayReqVo);
            String resStr = wechatPayHttpsRequest.sendPost(PayPropertiesUtils.getString("wechat.prePayOrderUrl"), postDataXML);
		/*if(Signature.checkIsSignValidFromResponseString(resStr)) {
			res = new Result(-1, "返回的数据签名,校验错误!");
		}*/
            WechatPrePayRespVo resResponsData = (WechatPrePayRespVo) Util.getObjectFromXML(resStr, WechatPrePayRespVo.class);
            if (resResponsData != null && GlobalConstants.WECHAT_PAY_SUCCESS_CODE.equals(resResponsData.getReturn_code())) {
                if (GlobalConstants.WECHAT_PAY_SUCCESS_CODE.equals(resResponsData.getResult_code())) {
                    Map returnMap = wechatPrePayReturnCreater(paymentTypeEnum,resResponsData);
                    returnMap.put("orderId",payExtendVo.getOrderId());
                    returnMap.put("payAmount",tradeLog.getPayAmount());
                    returnMap.put("income",tradeLog.getIncome());
                    returnMap.put("rewardFanpiao",tradeLog.getRewardFanpiao());
                    returnMap.put("incomeAmount",tradeLog.getIncomeAmount());
                    resultBean.setData(returnMap);
                } else {
                    resultBean = new ResultBean(ResultCode.PayWechatPreReqError.get_code(), ResultCode.PayWechatPreReqError.getMsg() + ";微信错误码：" + resResponsData.getReturn_code(), resResponsData);
                }
            } else {
                resultBean = new ResultBean(ResultCode.PayWechatReqError, null);
            }
            //记录操作日志
            this.payReqLogDao.savePayReqLog(payExtendVo.getOrderId(),payExtendVo.getUserId(), PayPropertiesUtils.getString("wechat.prePayOrderUrl"), paymentTypeEnum.getPaymentType(), postDataXML, resStr, resultBean.getCode());
        }catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
            return new ResultBean(ResultCode.UNSUCCESS,null);
        }
        return resultBean;
    }

    @Override
    public ResultBean<ThridPartyNotifyVo> thridPartyPayNotifyParse(ThridPartyNotifyVo thridPartyNotifyVo) {
        ResultBean<ThridPartyNotifyVo> resultBean = new ResultBean<ThridPartyNotifyVo>(ResultCode.SUCCESS,null);
        try {
            String xmlStr = thridPartyNotifyVo.getWechatRequstParamStr();
            if (Signature.checkIsSignValidFromResponseString(xmlStr)) {
                Map<String, Object> resMap = XMLParser.getMapFromXML(xmlStr);
                if (!CollectionUtils.isEmpty(resMap)) {
                    if (GlobalConstants.WECHAT_PAY_SUCCESS_CODE.equals(String.valueOf(resMap.get("return_code")))) {
                        if (GlobalConstants.WECHAT_PAY_SUCCESS_CODE.equals(String.valueOf(resMap.get("result_code")))) {
                            resultBean = new ResultBean(ResultCode.SUCCESS, resMap);
                        } else {
                            //微信支付 业务错误
                            String msg = ResultCode.PayWechatNotifyError.getMsg() + ";微信错误码：" + String.valueOf(resMap.get("err_code"));
                            resultBean = new ResultBean(ResultCode.PayWechatNotifyError.get_code(), msg, resMap);
                        }
                        thridPartyNotifyVo.setWechatParseCode(resultBean.getCode());
                        thridPartyNotifyVo.setWechatParseMsg(resultBean.getMsg());
                        thridPartyNotifyVo.setOrderId(String.valueOf(resMap.get("out_trade_no")));
                        thridPartyNotifyVo.setThirdPartyTradeNo(String.valueOf(resMap.get("transaction_id")));
                        resultBean.setData(thridPartyNotifyVo);
                    } else {
                        //通信失败
                        resultBean = new ResultBean(ResultCode.UNSUCCESS.get_code(), String.valueOf(resMap.get("return_msg")), null);
                    }
                } else {
                    //回调返回参数为空
                    resultBean = new ResultBean(ResultCode.UNSUCCESS.get_code(), ResultCode.PayNotifyParamEmpty.getMsg(), null);
                }
            } else {
                //签名检查失败
                resultBean = new ResultBean(ResultCode.UNSUCCESS.get_code(), ResultCode.PayWechatSingError.getMsg(), null);
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
            return new ResultBean(ResultCode.UNSUCCESS,null);
        }
        return resultBean;
    }

    @Override
    public ResultBean thridPartyPayNotify(String orderId,ThridPartyNotifyVo thridPartyNotifyVo){
        ResultBean resultBean = new ResultBean(ResultCode.SUCCESS,NOTFIY_EXCEPTION_IS_HANDLER);
        try {
            if (thridPartyNotifyVo.getWechatParseCode() != ResultCode.SUCCESS.get_code()) {
                resultBean = new ResultBean(thridPartyNotifyVo.getWechatParseCode(), thridPartyNotifyVo.getWechatParseMsg(), NOTFIY_EXCEPTION_IS_HANDLER);
            }
            //进行回调通知保存
            payReqLogDao.updatePayReqNotifyInfo(orderId, thridPartyNotifyVo.getWechatParseCode(), thridPartyNotifyVo.getWechatParseMsg(), thridPartyNotifyVo.getWechatRequstParamStr());
        } catch (Exception e) {
            logger.error(e.getMessage());
            resultBean = new ResultBean(ResultCode.UNSUCCESS,NOTFIY_EXCEPTION_IS_NOT_HANDLER);
        }
        return resultBean;
    }


    /**
     * 组装支付返回参数Map
     * @param paymentTypeEnum
     * @param prePayResData
     * @return
     */
    private Map wechatPrePayReturnCreater(PaymentTypeEnum paymentTypeEnum, WechatPrePayRespVo prePayResData) {
        Map payReqMap = new HashMap();
        if(paymentTypeEnum.getPaymentType() == paymentTypeEnum.ANDROID_WECHAT_PAY.getAccountType()) {
            //app支付返回app发起参数信息
            payReqMap.put("appid",prePayResData.getAppid());
            payReqMap.put("partnerid",prePayResData.getMch_id());
            payReqMap.put("prepayid",prePayResData.getPrepay_id());
            payReqMap.put("noncestr", RandomStringGenerator.getRandomStringByLength(32));
            payReqMap.put("timestamp", DateUtil.getTimeStamp());
            payReqMap.put("package","Sign=WXPay");
            payReqMap.put("sign", Signature.getSign(payReqMap));
            payReqMap.put("packageValue","Sign=WXPay");
        } else if(paymentTypeEnum.getPaymentType() == paymentTypeEnum.PC_WECHAT_PAY.getPaymentType()
                || paymentTypeEnum.getPaymentType() == paymentTypeEnum.WECHAT_PUBLIC_ACOOUNT_PAY.getPaymentType()) {
            //pc和公共账号支付返回二维码url
            payReqMap.put("scanCodeUrl",prePayResData.getCode_url());
        }
        return payReqMap;
    }

}
